//
//  DDViewController.swift
//  MoyaHttpDemo
//
//  Created by 林兴栋 on 2021/5/25.
//

import UIKit
import RxSwift
import RxCocoa
import Moya_ObjectMapper
import ObjectMapper
import Moya
import SnapKit

class DDViewController: UIViewController {
    
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        // Do any additional setup after loading the view.
        let btn = UIButton.create(title: "不推荐方法请求", color: .white, backColor: .orange)
        let btn2 = UIButton.create(title: "推荐方法请求", color: .white, backColor: .orange)
        
        view.addSubview(btn)
        view.addSubview(btn2)
        
        btn.snp.makeConstraints { make in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.centerX.equalToSuperview()
            make.top.equalTo(100)
        }
        btn2.snp.makeConstraints { make in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.centerX.equalToSuperview()
            make.top.equalTo(btn.snp.bottom).offset(50)
        }
        
        btn.rx.tap.bind { [weak self] in
            self?.getHttpInfo()
        }.disposed(by: disposeBag)
        
        btn2.rx.tap.bind { [weak self] in
            self?.getHttpGoodInfo()
        }.disposed(by: disposeBag)
        
        
    }
    
    var listArr:[DDModel]?{
        didSet {
            guard let tem = listArr else {
                return
            }
            print(tem)
        }
    }
    
    /// 不推荐方法
    func getHttpInfo() {
        NetworkManage.rx.request(.domeOne)
            .filterSuccessfulStatusCodes()
            .mapObject(DDBaseArrayModel<DDModel>.self)
            .subscribe { [weak self] result in
                self?.listArr = result.data
            } onError: { _ in
                
            }.disposed(by: disposeBag)

    }
    
    /// 推荐方法
    func getHttpGoodInfo() {
        NetworkManage.ddRequestArray(.domeOne, DDModel.self)
            .subscribe { [weak self] result in
                self?.listArr = result
            } onError: { error in
                
            }.disposed(by: disposeBag)
    }
    
    
}

// MARK:- 网络请求相关
/// DDMoyaHttp下的所有网络管理对象
#if DEBUG
let NetworkManage = MoyaProvider<DDMoyaHttp>(requestClosure: requestTimeoutClosure, plugins: [
    NetworkLoggerPlugin(configuration: NetworkLoggerPlugin.Configuration(logOptions:.verbose))
])
#else
let NetworkManage = MoyaProvider<DDMoyaHttp>(requestClosure: requestTimeoutClosure)
#endif

//设置请求超时时间
let requestTimeoutClosure = { (endpoint: Endpoint, done: @escaping MoyaProvider<DDMoyaHttp>.RequestResultClosure) in
    do {
        var request = try endpoint.urlRequest()
        request.timeoutInterval = 30
        done(.success(request))
    } catch {
        return
    }
}

/// 接口玫举值
enum DDMoyaHttp {
    case domeOne
    case domeTwo
}

extension DDMoyaHttp: TargetType {
    
    var baseURL: URL {
        switch self {
        case .domeOne:
            return URL(string: "https://api.silaishi.com")!
        default:
            return URL(string: "https://api.silaishi.com")!
        }
    }
    
    var path: String {
        switch self {
        case .domeOne:
            return "/1.0.0/mtlyw/getIndexCampList"
        default:
            return ""
        }
    }
    
    var method: Moya.Method {
        switch self {
        case .domeOne:
            return .get
        default:
            return .get
        }
    }
    
    var sampleData: Data {
        return "".data(using: String.Encoding.utf8)!
    }
    
    var task: Task {
        switch self {
        case .domeOne:
            return .requestPlain
        default:
            return .requestPlain
        }
    }
    
    var headers: [String : String]? {
        switch self {
        case .domeOne:
            return ["name":"强仔"]
        default:
            return [:]
        }
    }
    
}

/// 扩展一下网络请求
extension MoyaProvider {
    
    /// data数据为对象
    func ddRequestObject<T: Mappable>(_ target: Target,_ model: T.Type) -> Single<T> {
        let temSingle = Single<T>.create { [weak self] single in
            let request = self?.rx.request(target)
                .filterSuccessfulStatusCodes()
                .mapObject(DDBaseObjectModel<T>.self)
                .subscribe(onSuccess: { (result) in
                    if result.code == 200, let data = result.data {
                        single(.success(data))
                    } else {
                        single(.error(DDError(msg: "", code: result.code ?? -1)))
                    }
                }) { (error) in
                    single(.error(DDError(msg: "你的网络开小差了", code: -1)))
                }
            return Disposables.create {
                request?.dispose()
            }
        }
        return temSingle
    }
    
    /// data数据为对象数组
    func ddRequestArray<T: Mappable>(_ target: Target,_ model: T.Type) -> Single<[T]> {
        let temSingle = Single<[T]>.create { [weak self] single in
            
            let request = self?.rx.request(target)
                .filterSuccessfulStatusCodes()
                .mapObject(DDBaseArrayModel<T>.self)
                .subscribe(onSuccess: { (result) in
                    if result.code == 200, let data = result.data {
                        single(.success(data))
                    } else {
                        single(.error(DDError(msg: "", code: result.code ?? -1)))
                    }
                }) { (error) in
                    single(.error(DDError(msg: "你的网络开小差了", code: -1)))
                }
            return Disposables.create {
                request?.dispose()
            }
        }
        return temSingle
    }
}


// MARK:- 数据模型
/// 某一个接口的模型
struct DDModel: Mappable {
    
    init?(map: Map) {
        
    }
    
    var id:String?
    var name:String?
    var b_ids:String?
    var b_names:String?
    var target_num:String?
    var open_num:String?
    var summary:String?
    var grade:String?
    var term:String?
    var level:String?
    var img:String?
    var status:String?
    var cdate:String?
    var udate:String?
    var start_days:String?
    var finish_rate:String?
    var study_status:String?
    var teacher_status:String?
    var start_date:String?
    
    mutating func mapping(map: Map) {
        id          <- (map["id"],DDAnyToString())
        name        <- (map["name"],DDAnyToString())
        b_ids       <- (map["b_ids"],DDAnyToString())
        b_names     <- (map["b_names"],DDAnyToString())
        target_num  <- (map["target_num"],DDAnyToString())
        open_num    <- (map["open_num"],DDAnyToString())
        summary     <- (map["summary"],DDAnyToString())
        grade       <- (map["grade"],DDAnyToString())
        term        <- (map["term"],DDAnyToString())
        level       <- (map["level"],DDAnyToString())
        img         <- (map["img"],DDAnyToString())
        status      <- (map["status"],DDAnyToString())
        cdate       <- (map["cdate"],DDAnyToString())
        udate       <- (map["udate"],DDAnyToString())
        start_days  <- (map["start_days"],DDAnyToString())
        finish_rate <- (map["finish_rate"],DDAnyToString())
        study_status    <- (map["study_status"],DDAnyToString())
        teacher_status  <- (map["teacher_status"],DDAnyToString())
        start_date      <- (map["start_date"],DDAnyToString())
        
    }
    
}

// MARK:- 自定义错误信息
/// 自定义错误信息
struct DDError: LocalizedError {
    
    init(msg: String, code: Int) {
        errorDescription = msg
        errorCode = code
    }
    
    var errorDescription: String?
    var errorCode: Int?
    
    var localizedDescription: String {
        return self.errorDescription ?? ""
    }
}

// MARK:- 最外层通用的模型
/// 最外层通用的模型数据
struct DDBaseArrayModel<T: Mappable>: Mappable {
    
    init?(map: Map) {
        
    }
    
    var code:Int?
    var data:[T]?
    
    
    mutating func mapping(map: Map) {
        code <- map["code"]
        data <- map["data"]
    }
}

/// 最外层通用的模型
struct DDBaseObjectModel<T: Mappable>: Mappable {
    
    init?(map: Map) {
        
    }
    
    var code:Int?
    var data:T?
    
    
    mutating func mapping(map: Map) {
        code <- map["code"]
        data <- map["data"]
    }
}

// MARK:- 数值或字符类型转为字符串处理
/// 数值或字符类型转为字符串处理 用法：id <- (map["id"],DDAnyToString())
class DDAnyToString: TransformType {
    typealias Object = String
    
    typealias JSON = String
    
    func transformFromJSON(_ value: Any?) -> String? {
        if let val = value as? NSNumber {
            return "\(val)"
        }
        if let val = value as? CGFloat {
            return "\(val)"
        }
        if let val = value as? Int {
            return "\(val)"
        }
        if let val = value as? Double {
            return "\(val)"
        }
        if let val = value as? String {
            return val
        }
        if let val = value as? Bool {
            return "\(val ? 1 : 0)"
        }
        return nil
    }
    
    func transformToJSON(_ value: String?) -> String? {
        return value
    }
    
}

// MARK:- 扩展按钮
extension UIButton{
    /// 快速创建一个按钮
    static func create(title:String = "",color:UIColor = .black,backColor:UIColor = .orange) -> UIButton {
        let btn = UIButton(type: .custom)
        btn.setTitle(title, for: .normal)
        btn.setTitleColor(color, for: .normal)
        btn.backgroundColor = backColor
        return btn
    }
}
